package com.ruoyi.web.controller.snmp;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 传感器Controller
 *
 * @author ruoyi
 * @date 2025-02-25
 */
@RestController
@RequestMapping("/snmp/sensorinfo")
public class SnmpSensorinfoController extends BaseController
{
    @Autowired
    private ISnmpSensorinfoService snmpSensorinfoService;
    @Autowired
    private ISnmpDeviceinfoService snmpDeviceinfoService;
    @Autowired
    private ISnmpSensorinfohistoryService snmpSensorinfohistoryService;

    @Autowired
    private ISnmpSensubjectdeviceService snmpSensubjectdeviceService;
    @Autowired
    private ISnmpSensubjectinfoService snmpSensubjectinfoService;
    @Autowired
    private ISnmpEquipclientService snmpEquipclientService;
    @Autowired
    private ISnmpEquipmentinfoService snmpEquipmentinfoService;
    private final WebClient webClient;
    public SnmpSensorinfoController(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.build();
    }
    /**
     * 查询传感器列表
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:list')")
    @GetMapping("/list")
    public TableDataInfo list(SnmpSensorinfo snmpSensorinfo)
    {
        startPage();
        List<SnmpSensorinfo> list = snmpSensorinfoService.selectSnmpSensorinfoList(snmpSensorinfo);
        return getDataTable(list);
    }
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:list')")
    @GetMapping("/list/all")
    public AjaxResult all()
    {
        SnmpSensorinfo snmpSensorinfo=new  SnmpSensorinfo();
        List<SnmpSensorinfo> list = snmpSensorinfoService.selectSnmpSensorinfoList(snmpSensorinfo);
        return success(list);
    }
    @GetMapping("/list/{deviceId}")
    public AjaxResult alllist(@PathVariable("deviceId") String deviceId)
    {
        SnmpSensorinfo snmpSensorinfo=new SnmpSensorinfo();
        snmpSensorinfo.setDeviceId(deviceId);
        List<SnmpSensorinfo> list = snmpSensorinfoService.selectSnmpSensorinfoList(snmpSensorinfo);
        return success(list);
    }
    /**
     * 导出传感器列表
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:export')")
    @Log(title = "传感器", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SnmpSensorinfo snmpSensorinfo)
    {
        List<SnmpSensorinfo> list = snmpSensorinfoService.selectSnmpSensorinfoList(snmpSensorinfo);
        ExcelUtil<SnmpSensorinfo> util = new ExcelUtil<SnmpSensorinfo>(SnmpSensorinfo.class);
        util.exportExcel(response, list, "传感器数据");
    }

    /**
     * 获取传感器详细信息
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:query')")
    @GetMapping(value = "/{sensorId}")
    public AjaxResult getInfo(@PathVariable("sensorId") String sensorId)
    {
        return success(snmpSensorinfoService.selectSnmpSensorinfoBySensorId(sensorId));
    }
    @CrossOrigin
    @GetMapping(value = "/byDevice/{deviceId}")
    public AjaxResult getSerInfo(@PathVariable("deviceId") String deviceId) {

        List<SnmpSensorinfo> resultlist = new ArrayList<>();
        // 解析 JSON 数据
        final JSONObject[] resultjson = {null};
        //查找传感器场景主题
        SnmpSensubjectdevice snmpSensubjectdevice = new SnmpSensubjectdevice();
        snmpSensubjectdevice.setDeviceId(deviceId);
        List<SnmpSensubjectdevice> obj1 = snmpSensubjectdeviceService.selectSnmpSensubjectdeviceList(snmpSensubjectdevice);
        if (obj1 == null || obj1.size() < 1) return error();
        SnmpSensubjectinfo snmpSensubjectinfo = new SnmpSensubjectinfo();
        List<SnmpSensubjectinfo> obj2 = null;

        for (SnmpSensubjectdevice obj : obj1
        ) {
            snmpSensubjectinfo = new SnmpSensubjectinfo();
            snmpSensubjectinfo.setSensorsubject(obj.getSensorsubject());
            obj2 = snmpSensubjectinfoService.selectSnmpSensubjectinfoList(snmpSensubjectinfo);
            if (obj2 == null || obj2.size() < 1) continue;

            //获得mqtt服务连接数据
            ///根据MQTT服务信息、场景主题获得连接信息
            SnmpEquipclient objequipclick = snmpEquipclientService.selectSnmpEquipclientById(Long.valueOf(obj.getSensorsubject()));
            if (objequipclick == null || objequipclick.getEquipmentid().length() < 1) continue;
            ///根据IP获得mqtt服务器信息
            SnmpEquipmentinfo snmpEquipmentinfo = new SnmpEquipmentinfo();
            snmpEquipmentinfo.setEquipmentid(objequipclick.getEquipmentid());
            List<SnmpEquipmentinfo> objequip = snmpEquipmentinfoService.selectSnmpEquipmentinfoList(snmpEquipmentinfo);
            if (objequip == null || objequip.size() < 1) continue;


            MemoryPersistence persistence = new MemoryPersistence();
            String BROKER = "tcp://" + objequip.get(0).getEquipmentip() + ":" + objequip.get(0).getPort(); // MQTT Broker 地址（换成你的）
            String TOPIC = objequipclick.getLoginname() + "/" + objequipclick.getPassworld();               // 订阅的主题（和 ESP32 发布的主题一致）
            String CLIENT_ID = objequipclick.getClientId();//""PC_MQTT_Client";      // 客户端 ID，可自定义
            try {
                // 创建 MQTT 客户端（使用内存持久化，不需要保存到磁盘）
                MqttClient mqttClient = new MqttClient(BROKER, CLIENT_ID, persistence);

                // 设置连接选项（这里用匿名登录，如果你的 Broker 启用了用户名密码，请参考下面注释配置）
                MqttConnectOptions connOpts = new MqttConnectOptions();
                connOpts.setCleanSession(true); // 每次连接都是新的会话

                System.out.println("🔌 正在连接到 MQTT Broker: " + BROKER);
                mqttClient.connect(connOpts);
                System.out.println("✅ MQTT 连接成功！");
                List<SnmpSensubjectinfo> finalObj = obj2;
                mqttClient.setCallback(new MqttCallback() {
                    @Override
                    public void connectionLost(Throwable cause) {
                        System.err.println("❌ 与 MQTT Broker 的连接已断开: " + cause.getMessage());
                    }

                    @Override
                    public void messageArrived(String topic, MqttMessage message) {
                        try {
                            String payload = new String(message.getPayload());
                            System.out.println("\n📩 收到 MQTT 消息 [主题: " + topic + "]");
                            // 解析 JSON 数据
                            JSONObject objson = new JSONObject(payload);
                            resultjson[0] = objson;

                            //

                            for (SnmpSensubjectinfo sensorItem : finalObj
                            ) {
                                SnmpSensorinfo entityresult = new SnmpSensorinfo();

                                double temperature = resultjson[0].getDouble(sensorItem.getSensorGetdata());
                                entityresult.setSensorInfo(String.valueOf(temperature));
                                entityresult.setSensorId(sensorItem.getSensorId());
                                entityresult.setSensorName(sensorItem.getSensorName());
                                entityresult.setSensorGetdata(sensorItem.getSensorGetdata());
                                //将值保存到历史信息表中
                                SnmpSensorinfohistory snmpSensorinfohistory = new SnmpSensorinfohistory();
                                snmpSensorinfohistory.setDeviceId(deviceId);
                                snmpSensorinfohistory.setSensorId(sensorItem.getSensorId());
                                snmpSensorinfohistory.setSensorValue(String.valueOf(temperature));
                                snmpSensorinfohistory.setCreateTime(new Date());
                                //snmpSensorinfohistoryService.insertSnmpSensorinfohistory(snmpSensorinfohistory);
                            }
                        } catch (Exception e) {
                            System.err.println("❌ 解析 JSON 或处理消息时出错: " + e.getMessage());
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void deliveryComplete(IMqttDeliveryToken token) {
                        // 不需要实现，因为我们只是订阅者，不发布消息
                    }
                });
                // 订阅主题
                System.out.println("🔔 正在订阅 MQTT 主题: " + TOPIC);
                mqttClient.subscribe(TOPIC);
                System.out.println("✅ 已订阅，开始接收数据。按 Ctrl+C 停止程序。");


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //直接配置在IP上的,已失效
        /*
        SnmpDeviceinfo deviceinfoEntity = snmpDeviceinfoService.selectSnmpDeviceinfoByDeviceId(deviceId);
        SnmpSensorinfo snmpSensorinfo = new SnmpSensorinfo();
        snmpSensorinfo.setDeviceId(deviceId);
        List<SnmpSensorinfo> list = snmpSensorinfoService.selectSnmpSensorinfoList(snmpSensorinfo);

        String urlstr = "http://" + deviceinfoEntity.getDeviceIp();
        CompletableFuture<List<SnmpSensorinfo>> futures = fetchSensorDataAsync(list, urlstr);

        // 等待所有异步任务完成
        List<SnmpSensorinfo> resultList = futures.join();*/


        return success(resultlist);
    }
    /**
     * 异步方法，用于发起HTTP请求
     */
    @Async
    public CompletableFuture<List<SnmpSensorinfo>> fetchSensorDataAsync(List<SnmpSensorinfo> arrysensorList,String urlstr) { // 构建请求URL

        return webClient.get()
                .uri(urlstr)
                .retrieve()
                .bodyToMono(Map.class)
                .map(response -> {
                    if (response != null) {
                        for (SnmpSensorinfo item:arrysensorList) {
                            if ( response.containsKey(item.getSensorGetdata())) {
                                item.setSensorInfo(response.get(item.getSensorGetdata()).toString());
                            } else {
                                System.out.println("无法找到字段 " + item.getSensorGetdata() + " 的值");
                            }
                        }
                    }
                    return arrysensorList; // 返回修改后的 item
                })
                .onErrorResume(error -> {
                    System.err.println("请求失败: " + error.getMessage());
                    return Mono.just(arrysensorList); // 发生错误时返回原始 item
                })
                .toFuture(); // 将 Mono 转换为 CompletableFuture
    }
    /**
     * 新增传感器z
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:add')")
    @Log(title = "传感器", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SnmpSensorinfo snmpSensorinfo)
    {
        return toAjax(snmpSensorinfoService.insertSnmpSensorinfo(snmpSensorinfo));
    }

    /**
     * 修改传感器
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:edit')")
    @Log(title = "传感器", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SnmpSensorinfo snmpSensorinfo)
    {
        return toAjax(snmpSensorinfoService.updateSnmpSensorinfo(snmpSensorinfo));
    }

    /**
     * 删除传感器
     */
    @PreAuthorize("@ss.hasPermi('snmp:sensorinfo:remove')")
    @Log(title = "传感器", businessType = BusinessType.DELETE)
	@DeleteMapping("/{sensorIds}")
    public AjaxResult remove(@PathVariable String[] sensorIds)
    {
        return toAjax(snmpSensorinfoService.deleteSnmpSensorinfoBySensorIds(sensorIds));
    }
}
